package cn.tf.tfpay.fap.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 本地文件查询,读写.
 * 
 * @author Administrator
 *
 */
@Slf4j
@Data
@RestController
public class FapController implements FapFacade {

	/** 允许访问的目录列表 */
	@Value("${allowAccessDirs}")
	private List<String> allowAccessDirs = new ArrayList<>();

	/** readAsBase64String方法,最大能读多大的文件,默认50M */
	@Value("${maxReadSize:52428800}")
	private int maxReadSize;

	@PostConstruct
	public void init() {
		log.info("FapController inited:" + this);
	}

	@Override
	public boolean exists(String path) {
		path = FapUtils.decodePath(path);
		return new File(path).exists();
	}

	//TODO  新建
	@Override
	public RemoteFile get(String path) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			return null;
		}

		RemoteFile f= FapUtils.buildRemoteFile(localFile);
		System.out.println(f);
		return f;
	}

	@Override
	public List<RemoteFile> list(String path, String regex) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "目录不存在:" + path);
		}
		if (!localFile.isDirectory()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "不是目录:" + path);
		}
		File[] childs = StringUtils.isEmpty(regex) ? localFile.listFiles()
				: localFile.listFiles((file, name) -> name.matches(regex));
		return Stream.of(childs).map(FapUtils::buildRemoteFile).collect(Collectors.toList());
	}

	@Override
	public boolean deleteFile(String path) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			return true;
		}
		if (localFile.isDirectory()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "路径是目录:" + path);
		}
		return FileUtils.deleteQuietly(localFile);
	}

	
	@Override
	public boolean deleteDir(String path) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			return true;
		}
		if (!localFile.isDirectory()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "路径不是目录:" + path);
		}
		return FileUtils.deleteQuietly(localFile);
	}
	
	@Override
	public boolean makeDir(String path) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "路径已存在:" + path+",且是目录?:"+localFile.isDirectory());
		}
		File parent = localFile.getParentFile();
		if (parent != null && !parent.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "上级目录不存在:" + path);
		}
		return localFile.mkdir();
	}
	
	@Override
	public void readStream(String path, HttpServletResponse response) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "文件不存在:" + path);
		}
		
		if (localFile.isDirectory()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "是目录:" + path);
		}

		try (FileInputStream fis = new FileInputStream(localFile)) {
			IOUtils.copy(fis, response.getOutputStream());
			response.getOutputStream().flush();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "文件读取异常:" + e.getMessage());
		}
	}

	@Override
	public String readBase64(String path) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (!localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "文件不存在:" + path);
		}
		if (localFile.length() > maxReadSize) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "文件太大,不能用此方式下载,你可以使用流的方式下载也可以调整阈值:" + path);
		}

		try {
			return Base64.encodeBase64String(FileUtils.readFileToByteArray(localFile));
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "文件读取异常:" + e.getMessage());
		}
	}

	@Override
	public long writeBase64(String path, String base64String) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "文件已存在:" + path);
		}

		try {
			FileUtils.writeByteArrayToFile(localFile, Base64.decodeBase64(base64String));
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "写文件异常:" + e.getMessage());
		}
		
		return localFile.length();
	}

	@Override
	public long writeStream(String path, HttpServletRequest request) {
		path = FapUtils.decodePath(path);
		File localFile = new File(path);
		if (localFile.exists()) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "文件已存在:" + path);
		}

		try(FileOutputStream fos=new FileOutputStream(localFile)) {
			IOUtils.copy(request.getInputStream(), fos);
			fos.flush();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "写文件异常:" + e.getMessage());
		}
		
		return localFile.length();
	}

}
